package com.chenfan.process.biz.impl;

import com.chenfan.infra.context.UserContextHolder;
import com.chenfan.infra.vo.UserVO;
import com.chenfan.notify.MessageClient;
import com.chenfan.process.dto.ApprovalCallBack;
import com.chenfan.process.entity.po.ApprovalPo;
import com.chenfan.process.entity.po.ProcessCarbonCopyPo;
import com.chenfan.process.entity.po.ProcessInstanceApprovePo;
import com.chenfan.process.entity.po.ProcessRelatedPo;
import com.chenfan.process.enums.CarbonCopyEnum;
import com.chenfan.process.enums.EventTypeEnums;
import com.chenfan.process.event.callback.CallbackEvent;
import com.chenfan.process.service.*;
import com.chenfan.process.util.TransactionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author liuming
 * @date 2022/1/12
 */
public abstract class BaseEventBiz {

    @Autowired
    protected ApplicationEventPublisher publisher;
    @Autowired
    protected ProcessCarbonCopyService carbonCopyService;
    @Autowired
    protected ApprovalService approvalService;
    @Autowired
    protected ProcessRelatedService processRelatedService;
    @Autowired
    protected ProcessInstanceApproveService instanceApproveService;
    @Autowired
    protected ApprovalTemplateService approvalTemplateService;
    @Autowired
    protected MessageClient messageClient;
    @Autowired
    protected ProcessNodeNotifyConfigService processNodeNotifyConfigService;
    @Autowired
    protected TemplateConfigService templateConfigService;

    public List<ApprovalCallBack.CarbonCopyDTO> carbonCopyList(ApprovalPo approval, Long approvalTemplateId,
        Long currentProcessId) {
        Optional<List<ProcessCarbonCopyPo>> ccOptional =
            carbonCopyService.listByProcessId(approvalTemplateId, currentProcessId);
        List<ProcessCarbonCopyPo> carbonCopies = ccOptional.get();
        List<ApprovalCallBack.CarbonCopyDTO> processList =
            carbonCopies.stream().map(ProcessCarbonCopyPo::toDTO).collect(Collectors.toList());

        // 创建人
        Optional<ProcessCarbonCopyPo> createOp = carbonCopies.stream()
            .filter(e -> Objects.equals(e.getType(), CarbonCopyEnum.APPROVAL_CREATE_PERSON.getCode())).findAny();
        if (createOp.isPresent()) {
            processList.add(ApprovalCallBack.CarbonCopyDTO.builder().userId(approval.getCreateBy())
                .type(CarbonCopyEnum.NORMAL.getCode()).userName(approval.getCreateName()).build());
        }
        // 所有人
        Optional<ProcessCarbonCopyPo> anyOp =
                carbonCopies.stream().filter(e -> Objects.equals(e.getType(), CarbonCopyEnum.ALL.getCode())).findAny();
        if (anyOp.isPresent()) {
            // 找到所有的人然后去重
            List<ProcessInstanceApprovePo> processInstances =
                    instanceApproveService.listApprovalInstance(Collections.singletonList(approval.getApprovalId()));
            List<ApprovalCallBack.CarbonCopyDTO> list = processInstances.stream().map(
                            e -> ApprovalCallBack.CarbonCopyDTO.builder().userId(e.getUserId()).userName(e.getUserName()).build())
                    .collect(Collectors.toList());
            processList.addAll(list);
        }
        processList = processList.stream().filter(ApprovalCallBack.CarbonCopyDTO::filter).distinct()
                .collect(Collectors.toList());
        return processList;
    }

    protected boolean dealWithEvent(Long approvalId, Long approvalTemplateId, Long currentProcessId) {
        // 通过
        ApprovalPo approval = approvalService.findApprovalByApprovalId(approvalId);
        List<ProcessRelatedPo> relatedPoList = processRelatedService
            .listProcessRelatedAfterProcessId(approvalTemplateId, approval.getVersion(), currentProcessId);
        if (CollectionUtils.isEmpty(relatedPoList)) {
            return true;
        }
        currentProcessId = relatedPoList.get(0).getProcessAfterId();
        List<ApprovalCallBack.CarbonCopyDTO> carbonCopies =
            carbonCopyList(approval, approvalTemplateId, currentProcessId);
        if (CollectionUtils.isEmpty(carbonCopies)) {
            return true;
        }
        // 所有人
        Optional<ApprovalCallBack.CarbonCopyDTO> any =
            carbonCopies.stream().filter(e -> Objects.equals(e.getType(), CarbonCopyEnum.ALL.getCode())).findAny();
        if (any.isPresent()) {
            // 找到所有的人然后去重
            List<ProcessInstanceApprovePo> processInstances =
                instanceApproveService.listApprovalInstance(Collections.singletonList(approvalId));
            List<ApprovalCallBack.CarbonCopyDTO> list = processInstances.stream().map(
                e -> ApprovalCallBack.CarbonCopyDTO.builder().userId(e.getUserId()).userName(e.getUserName()).build())
                .collect(Collectors.toList());
            carbonCopies.addAll(list);
        }

        // 去重
        carbonCopies = carbonCopies.stream().filter(ApprovalCallBack.CarbonCopyDTO::filter).distinct()
            .collect(Collectors.toList());
        UserVO userVo = UserContextHolder.getUserVo();
        ApprovalCallBack.ApprovalCallBackBuilder builder = ApprovalCallBack.builder();

        if (Objects.nonNull(userVo)) {
            builder.userId(userVo.getUserId());
            builder.userName(userVo.getRealName());
        }
        CallbackEvent callbackEvent = new CallbackEvent(
                builder.approvalFinished(true).approvalFlag(true).nextApprovalUserId(null).nextApprovalUserName("")
                        .eventType(EventTypeEnums.FINISH.getCode()).approvalId(approvalId).carbonCopyList(carbonCopies).build(),
                UserContextHolder.getToken());
        TransactionUtils.afterCommit(() -> publisher.publishEvent(callbackEvent));
        return false;
    }
}
